
import SQLite

class DbMessage : DbBase {
    var message: Table = Table("message")
    let _id = Expression<Int64>("id")
    let _target = Expression<String>("target")
    let _originalUser = Expression<String>("originalUser")
    let _msgType = Expression<Int>("msgType")
    let _direction = Expression<Int>("direction")
    let _status = Expression<Int>("status")
    let _timestamp = Expression<Int64>("timestamp")
    let _content = Expression<String>("content")
    let _msgHash = Expression<String>("msgHash")
    let _msgHasho = Expression<String>("msgHasho")
    let _extra = Expression<String>("extra")
    let _toUsers = Expression<String>("toUsers")
    let _text = Expression<String>("text")

    func open(){
        do{
            try getDb()!.run(message.create(ifNotExists: true) { t in
                t.column(_id, primaryKey: .autoincrement)
                t.column(_target)
                t.column(_msgType)
                t.column(_direction)
                t.column(_status)
                t.column(_timestamp)
                t.column(_content)
                t.column(_msgHash, unique: true)
                t.column(_msgHasho)
                t.column(_extra)
                t.column(_toUsers)
                t.column(_originalUser)
                t.column(_text)
            })
            try getDb()!.run(message.createIndex(_msgHash, ifNotExists: true))
        }catch{
            print("\(error)")
        }        
    }
    func toInfo(_ row:Row)->DMCCMessage{
        let m = DMCCMessage()
        m.id = row[_id]
        m.target = row[_target]
        m.originalUser = row[_originalUser]
        m.toUsers = row[_toUsers]
        m.timestamp = row[_timestamp]
        m.extra = row[_extra]
        m.msgHash = row[_msgHash]
        m.msgHasho = row[_msgHasho]
        m.content = row[_content]
        m.msgType = OsnMessageContentType(rawValue: row[_msgType])
        m.direction = OsnMessageDirection(rawValue: row[_direction])
        m.status = OsnMessageStatus(rawValue: row[_status])
        m.content = gosnContent.fromJson(OsnUtils.toJson(row[_content]) ?? [:])
        m.text = row[_text]
        return m
    }
    func getMessageInfo(_ mid:Int64) -> DMCCMessage? {
        do{
            for messages in try getDb()!.prepare(message.filter(_id == mid)) {
                return toInfo(messages)
            }
        }catch{
            print("\(error)")
        }
        return nil
    }
    func getMessageFromHash(_ hash:String) -> DMCCMessage? {
        do{
            for messages in try getDb()!.prepare(message.filter(_msgHash == hash)) {
                return toInfo(messages)
            }
        }catch{
            print("\(error)")
        }
        return nil
    }
    func getMessageFromHasho(_ hash:String) -> DMCCMessage? {
        do{
            for messages in try getDb()!.prepare(message.filter(_msgHasho == hash)) {
                return toInfo(messages)
            }
        }catch{
            print("\(error)")
        }
        return nil
    }
    func addMessageInfo(_ info:DMCCMessage) -> Bool {
        do{
            let content = OsnUtils.toString(gosnContent.toJson(info.content as? OsnMessageContent ?? OsnMessageContent(),isDB: true))
            return try getDb()!.run(message.upsert(
                _target <- info.target,
                _originalUser <- info.originalUser,
                _msgType <- info.msgType.rawValue,
                _direction <- info.direction.rawValue,
                _status <- info.status.rawValue,
                _timestamp <- info.timestamp,
                _content <- content ?? "",
                _msgHash <- info.msgHash,
                _msgHasho <- info.msgHasho,
                _extra <- info.extra,
                _toUsers <- info.toUsers,
                _text <- (info.content as? OsnTextMessageContent)?.data ?? "",
                onConflictOf: _msgHash)) >= 0
        }catch{
            print("\(error)")
        }
        return false
    }
    func delMessageInfo(_ osnId:String) ->Bool {
        do{
            return try getDb()!.run(message.filter(_target == osnId).delete()) > 0
        }catch{
            print("\(error)")
        }
        return false
    }
    
    func delOneMessage(_ hash:String) ->Bool {
        do{
            return try getDb()!.run(message.filter(_msgHash == hash).delete()) > 0
        }catch{
            print("\(error)")
        }
        return false
    }
    
    func listMessageInfo(_ osnId:String, _ timestamp:Int64, _ size:Int) ->[DMCCMessage] {
        var ms:[DMCCMessage] = []
        var tm = Int64(0)
        var time = timestamp

        if timestamp == 0 {
            // 获取当前时间的时间戳（以秒为单位）
            let currentTimeIntervalSince1970 = Date().timeIntervalSince1970
            // 转换为毫秒
            let currentTimeIntervalInMilliseconds = currentTimeIntervalSince1970 * 1000
            // 加上1000年的毫秒数
            time = Int64(currentTimeIntervalInMilliseconds + 31536000000)
        }
        do{
            for msg in try getDb()!.prepare(
                message.filter(_target == osnId && _timestamp < time).order(_timestamp.desc).limit(size)) {
                let u = toInfo(msg)
                if ms.count == 0 {
                    tm = u.timestamp
                }
                let timeInt = tm - u.timestamp
                if ms.count > 0 {
                    let newMsg = ms.last!
                    if timeInt > 200000 {
                        tm = u.timestamp
                        u.showTime = false
                        newMsg.showTime = true
                    }else{
                        u.showTime = false
                    }
                }
                
                ms.append(u)
            }
            return ms
        }catch{
            print("\(error)")
        }
        return ms
    }
    
    func updateMessageInfo(_ hash:String, _ updater: Setter) -> Bool {
        do{
            return try getDb()!.run(message.filter(_msgHash == hash).update(updater)) >= 0
            
        }catch{
            print("\(error)")
        }
        return false
    }
    func searchMessage(_ osnId:String,_ text:String, _ start:Int64, _ end:Int64) -> [DMCCMessage] {
        var ms:[DMCCMessage] = []
        do{
            for msg in try getDb()!.prepare(
                message.filter(_target == osnId && _text.like("%"+text+"%") && _timestamp > start && _timestamp < end).order(_timestamp.desc)) {
                let u = toInfo(msg)
                ms.append(u)
            }
        }catch{
            print("\(error)")
        }
        return ms
    }
}
let dbMessage = DbMessage()
